package spring.lottery.server.mq;

import cn.hutool.crypto.SecureUtil;
import cn.hutool.extra.compress.extractor.SevenZExtractor;
import cn.hutool.log.Log;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import spring.lottery.common.exception.ServerException;
import spring.lottery.common.pojo.DrawHtml;
import spring.lottery.common.util.MailUtil;
import spring.lottery.common.util.SerializeUtil;
import spring.lottery.common.util.ToStdDate;
import spring.lottery.controller.param.DrawPrizesData;
import spring.lottery.dao.dataObject.WinningRecordDO;
import spring.lottery.dao.mapper.UserMapper;
import spring.lottery.server.ActivitiesServer;
import spring.lottery.server.DrawPrizeServer;
import spring.lottery.server.MqReceiver;
import spring.lottery.server.activityStatus.ActivityStatusManager;
import spring.lottery.server.dto.UserDto;

import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static spring.lottery.common.config.DirectRabbitConfig.QUEUE_NAME;

/**
 * 这个是中奖逻辑
 * 活动id 中奖人 奖品
 */
@Slf4j
@Component
@RabbitListener(queues = QUEUE_NAME)
public class MqReceiverImp implements MqReceiver {

    @Autowired
    MailUtil mailUtil;
    @Autowired
    DrawPrizeServer drawPrizeServer;
    @Autowired
    ActivityStatusManager activityStatusManager;
    @Autowired
    UserMapper userMapper;
    @Autowired
    ThreadPoolTaskExecutor threadPoolTaskExecutor;
    @Autowired
    ActivitiesServer activitiesServer;

    @RabbitHandler
    @Transactional(rollbackFor = Exception.class)
    public void receive(String message) {
        log.info("消费者收到消息 message: {}", message);

        DrawPrizesData drawPrizesData = SerializeUtil.unEncode(message, DrawPrizesData.class);

        //验证信息是否正确
        drawPrizeServer.verify(drawPrizesData);

        log.info("中奖者校验通过");

        //这里开始根据信息来改变状态
        /**
         * 责任链模式：
         * 使用一个map来储存需要执行的策略方法并按一定的顺序执行
         * 策略模式：
         * 将每种需要执行的方法用一个接口定义，并实现起对应的实现类
         */
        //扭转活动状态
        activityStatusManager.convert(drawPrizesData);

        //保存中奖信息
        List<WinningRecordDO> winningRecordDOS = activitiesServer.saveWinningInfo(drawPrizesData);

        //通知中奖
        sendMessage(winningRecordDOS);
    }

    private void sendMessage(List<WinningRecordDO> winningRecordDOS) {

        threadPoolTaskExecutor.execute(() -> {

            winningRecordDOS.forEach(w -> {

                try {

                String date = ToStdDate.tran(w.getWinningTime());

                    String html = new DrawHtml().toString();

                    String msg = html.replace("%%s1", w.getWinnerName())
                            .replace("%%s2", w.getActivityName())
                            .replace("%%s3", w.getPrizeTier())
                            .replace("%%s4", w.getPrizeName())
                            .replace("%%s5", date);

                    Boolean b = mailUtil.sendHtmlMail(w.getWinnerEmail(), "中奖啦", msg);

                    log.info("中奖信息发送成功 msg: {}", date);

                }catch (Exception e) {
                    log.error("中奖信息发送失败 sendInfo: {} \nmsg: {}", w, e.getMessage(), e);
                }
            });
        });
    }
}
